'''
Case Type： 故障&可靠性测试
Case Name： 多次数据库主备failover，运行TPCC；
Create At: 2020/07/20
@zou_jialiang0505328114
Descption:
步骤 1.启动主备数据库，判断数据库状态；
步骤 2.运行tpcc；
步骤 3.运行tpcc时，备机数据库直接failover；
'''
import os
import unittest
import time
from yat.test import macro
from yat.test import Node
from testcase.utils.CommonSH import *
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.ComThread import ComThread


class Deletaduit(unittest.TestCase):
    commonshpri = CommonSH('PrimaryDbUser')
    commonshsta_1 = CommonSH('Standby1DbUser')
    commonshsta_2 = CommonSH('Standby2DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('------------Opengauss_Reliability_Dbsys_Case158.py start------------')
        self.rootNode = Node()
        self.com = Common()
        self.Constant = Constant()
        self.db_primary_user = Node(node='PrimaryDbUser')
        self.db_primary_root = Node(node='PrimaryRoot')
        self.db_standby1_root = Node(node='Standby1Root')
        self.db_standby1_user = Node(node='Standby1DbUser')
        self.tpcc_path = macro.TPCC_PATH

    def test_startdb(self):
        sourcecmd = f'source {macro.DB_ENV_PATH}'
        failovercmd = f'{sourcecmd};gs_ctl failover -D {macro.DB_INSTANCE_PATH};gs_om -t refreshconf;'
        # 运行tpcc；
        tpcc_thread = ComThread(self.com.startTPCC, args=(self.rootNode, self.tpcc_path,))
        tpcc_thread.setDaemon(True)
        tpcc_thread.start()

        time.sleep(1)

        # 运行tpcc时，备机数据库直接failover；
        msg2 = self.db_standby1_user.sh(failovercmd).result()
        self.log.info(msg2)
        self.assertIn(self.Constant.FAILOVER_SUCCESS_MSG, msg2)
        self.assertIn(self.Constant.REFRESH_FAIL_MSG, msg2)

        tpcc_thread.join(int(macro.TPCC_RUN_MAX_TIME) * 2)
        tpcc_result = tpcc_thread.get_result()
        self.log.info(tpcc_result)
        self.assertIn(self.Constant.TPCC_SUCCESS_MSG, tpcc_result)

        # 校验刷脏页是否完成
        self.log.info('校验刷脏页是否完成')
        dirty_page_finshed_flag = self.commonshpri.check_whether_remain_dirty_page()
        self.assertTrue(dirty_page_finshed_flag)

        # 校验备机是否完成数据同步,备1执行了failover，因此仅校验备2
        self.log.info('校验备机是否完成数据同步')
        flag_2 = self.commonshsta_2.check_data_consistency()
        self.assertTrue(flag_2)

        self.log.info("重启数据库")
        stop_msg = self.commonshpri.stopDbCluster()
        self.assertTrue(stop_msg)

        start_msg = self.commonshpri.startDbCluster()
        self.log.info(start_msg)

        db_status = self.commonshpri.getDbClusterStatus('detail')
        self.assertIn(self.Constant.CLUSTER_DEGRADED_MSG, db_status)

        self.log.info("备机重建")
        msg = self.commonshsta_1.executeGsctl('build', self.Constant.BUILD_SUCCESS_MSG)
        self.log.info(msg)
        self.assertTrue(msg)

        time.sleep(5)

        status = self.commonshpri.getDbClusterStatus('detail')
        self.log.info(status)

        self.log.info("主备杀进程")
        msg11 = self.com.kill_pid(self.db_standby1_root, 9)
        self.assertEqual(msg11, '')
        msg11 = self.com.kill_pid(self.db_primary_root, 9)
        self.assertEqual(msg11, '')

        self.log.info("重新启动数据库")
        start_msg = self.commonshpri.startDbCluster()
        self.log.info(start_msg)
        self.assertTrue(start_msg)

        status = self.commonshpri.getDbClusterStatus('detail')
        self.log.info(status)

    def tearDown(self):
        self.log.info("-------------------------------this is tearDown-----------------------------")
        self.log.info(
            '------------------------------------reliability_dbsys158.py finish------------------------------------')
